/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.tabbedproperties.composites;

import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.uml2.common.edit.command.ChangeCommand;
import org.eclipse.uml2.uml.BehavioralFeature;
import org.eclipse.uml2.uml.Parameter;

import com.cea.papyrus.core.commands.EMFtoGEFWrapCommand;
import com.cea.papyrus.core.commands.MoveInListCommand;
import com.cea.papyrus.core.commands.UMLElementCreateCommand;
import com.cea.papyrus.core.commands.factories.UMLDi2ElementDeleteFactory;
import com.cea.papyrus.core.editor.CommandStackUtils;
import com.cea.papyrus.core.ui.dialogs.ExtendedDirectEditionDialog;
import com.cea.papyrus.core.utils.UMLObjectLabelProvider;
import com.cea.papyrus.extensionpoints.editors.configuration.IDirectEditorConfiguration;
import com.cea.papyrus.extensionpoints.editors.utils.DirectEditorsUtil;
import com.cea.papyrus.umlutils.Element;

/**
 * Composite that displays the parameters of a behavior.
 */
public class ParametersComposite extends DecoratedTableComposite implements ISectionComposite {

	/**
	 * Creates a new ParametersComposite.
	 */
	public ParametersComposite() {
		super("Parameters");
	}

	/**  key to access UML Data from table items */ 
	private final static String KEY = "parameter_data";

	/** Behavior for which methods are displayed */
	private BehavioralFeature behavioralFeature;

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setElement(Element element) {
		super.setElement(element);
		this.behavioralFeature = (BehavioralFeature)element.getUml2Element();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void refresh() {
		if( !table.isDisposed()&& (behavioralFeature!=null)){
			int[] selections= table.getSelectionIndices();
			
			// Remove parameters from table 
			table.removeAll();

			// Read and add parameter
			Iterator<Parameter> it = behavioralFeature.getOwnedParameters().iterator();
			while (it.hasNext()) {
				Parameter parameter = it.next();
				TableItem item = new TableItem(table, SWT.BORDER);

				UMLObjectLabelProvider labelProvider = new UMLObjectLabelProvider();
				item.setImage(labelProvider.getImage(parameter));				
				item.setText(labelProvider.getText(parameter, true));
				item.setData(KEY, new com.cea.papyrus.umlutils.Parameter(parameter));
			}
			
			table.select(selections);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void addButtonPressed() {
		Command command = new UMLElementCreateCommand(Parameter.class, behavioralFeature);
		CommandStack stack = CommandStackUtils.getCommandStack();
		Assert.isNotNull(stack, "Impossible to adapt current editor into a CommandStack");
		stack.execute(command);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void downButtonPressed() {
		CompoundCommand compoundCommand = new CompoundCommand();
		TableItem[] tableItems = table.getSelection();
		int[] selections = table.getSelectionIndices();

		for(int i = (tableItems.length-1); i >= 0; i--) {
			// get parameters list
			List<Parameter> parameters = behavioralFeature.getOwnedParameters();
			// get parameter
			Parameter parameter  = ((com.cea.papyrus.umlutils.Parameter) tableItems[i].getData(KEY)).getUml2Parameter();
			int newIndex = table.indexOf(tableItems[i]) + 1;
			if(newIndex < parameters.size()) {
				compoundCommand.add(new MoveInListCommand(parameters, parameter, newIndex));
				// update selection indexes
				selections[i]=selections[i]+1;
			}
		}
		CommandStack stack = CommandStackUtils.getCommandStack();
		Assert.isNotNull(stack, "Impossible to adapt current editor into a CommandStack");
		stack.execute(compoundCommand);
		// update table selection
		table.setSelection(selections);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void editItem(TableItem item) {
		if (item == null) {
			return;
		}

		// parameter linked to the item
		final com.cea.papyrus.umlutils.Parameter parameter = (com.cea.papyrus.umlutils.Parameter)item.getData(KEY);

		// getEditor for this language
		final IDirectEditorConfiguration configuration = DirectEditorsUtil.findEditorConfiguration("UML", "org.eclipse.uml2.uml.Parameter"); 
		configuration.setLanguage("UML");
		configuration.preEditAction(parameter.getUml2Parameter());
		final ExtendedDirectEditionDialog dialog = new ExtendedDirectEditionDialog(table.getShell(),
				parameter.getUml2Parameter(),
				configuration.getTextToEdit(parameter.getUml2Parameter()),
				configuration);
		if(Window.OK==dialog.open()) {
			// apply modifications
			final AdapterFactoryEditingDomain emfDomain = getModelManager().getDiResourceSet().getEditingDomain();
			EMFtoGEFWrapCommand command = new EMFtoGEFWrapCommand(emfDomain) {
				@Override
				public org.eclipse.emf.common.command.Command createEMFCommand() {
					return new ChangeCommand(emfDomain, new Runnable() {
						public void run() {configuration.postEditAction(parameter.getUml2Parameter(), dialog.getValue());};
					}, "Edit Label", "Edit the label of the selected element");
				}
			};
			CommandStackUtils.getCommandStack().execute(command);
		}
		refresh();

	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void removeButtonPressed() {
		CompoundCommand command = new CompoundCommand(); 
		// get selection and delete it
		TableItem[] tableItems = table.getSelection();
		
		for(int i = 0; i < tableItems.length ; i++) {
			// get parameter
			com.cea.papyrus.umlutils.Parameter parameter = (com.cea.papyrus.umlutils.Parameter) tableItems[i].getData(KEY);
			command.add(UMLDi2ElementDeleteFactory.eINSTANCE.createCommand(parameter.getUml2Parameter()));
		}
		CommandStack stack = CommandStackUtils.getCommandStack();
		Assert.isNotNull(stack, "Impossible to adapt current editor into a CommandStack");
		stack.execute(command);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void upButtonPressed() {
		CompoundCommand compoundCommand = new CompoundCommand();
		TableItem[] tableItems = table.getSelection();
		// keep trace of the previous selection
		int[] selections = table.getSelectionIndices();
		
		List<Parameter> parameters = behavioralFeature.getOwnedParameters();
		for(int i = 0; i < tableItems.length ; i++) {
			// get parameter
			Parameter parameter = ((com.cea.papyrus.umlutils.Parameter) tableItems[i].getData(KEY)).getUml2Parameter();
			int newIndex = table.indexOf(tableItems[i]) - 1;
			if (newIndex >= 0) {
				compoundCommand.add(new MoveInListCommand(parameters, parameter, newIndex));
				// update selection table
				selections[i] = selections[i]-1;
			}
		}
		CommandStack stack = CommandStackUtils.getCommandStack();
		Assert.isNotNull(stack, "Impossible to adapt current editor into a CommandStack");
		stack.execute(compoundCommand);
		
		// update selection
		table.setSelection(selections);
	}
}
